﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Security.Cryptography;

namespace jobhuntr.BusinessLogic
{
    public class UserService
    {
        private jobhuntrDataContext _dc;

        public User CreateUser(string UserName, string Email, string FirstName, string Surname, string Password)
        {
            //Check to make sure username doesnt exisit.
            if (GetUser(UserName) != null)
                throw new ApplicationException("Username already exists");


            //Create User
            User newUser = new User();

            newUser.UserName = UserName;
            newUser.Email = Email;
            newUser.FirstName = FirstName;
            newUser.Surname = Surname;

            //Password 
            newUser.PasswordSalt = GenerateSalt();
            string SaltedPassword = Password + newUser.PasswordSalt;


            newUser.PasswordHash = ComputeHash(SaltedPassword);




            jobhuntrDataContext dataContext = CreateDataContext();
            {

                //Commit to Database            
                dataContext.Users.InsertOnSubmit(newUser);

                dataContext.SubmitChanges();
                //Throws SQLException when UNIQUE Keys are violated.

            }
            return newUser;
        }

        public User GetUser(string UserName)
        {
            try
            {
                jobhuntrDataContext dataContext = CreateDataContext();
                {

                    User theUser = dataContext.Users.Where(u => u.UserName == UserName).First();
                    return theUser;
                }
            }
            catch (Exception e)
            {
                return null;
                throw e;
            }
            
        }

        public User GetUserByEmail(string Email)
        {
            jobhuntrDataContext dataContext = CreateDataContext();
            {

                User theUser = dataContext.Users.Where(u => u.Email == Email).First();
                return theUser;
            }
        }

        public bool ValidatePassword(string UserName, string Password)
        {
            User theUser = GetUser(UserName);
            if (theUser == null)
                throw new ApplicationException("User does not exisit");

            string HashedPassword = ComputeHash(Password + theUser.PasswordSalt);
            if (HashedPassword == theUser.PasswordHash)
                return true;
            else
                return false;

        }

        public bool ChangePassword(string UserName, string Password, string OldPassword)
        {
            if (ValidatePassword(UserName, OldPassword) == false)
                return false;

            User u = GetUser(UserName);
            if (u == null)
                throw new ApplicationException("User does not exisit");

            //generate new password hash
            u.PasswordSalt = GenerateSalt();
            u.PasswordHash = ComputeHash(Password + u.PasswordSalt);

            UpdateUser(u);
            return true;
        }

        private void UpdateUser(User theUser)
        {


            jobhuntrDataContext dataContext = CreateDataContext();
            {

                //dataContext.Users.Attach(theUser,true );
                dataContext.SubmitChanges();
            }


        }


        private jobhuntrDataContext CreateDataContext()
        {
            if (_dc == null)
                _dc = new jobhuntrDataContext(ConfigurationManager.ConnectionStrings["JobHuntrConnectionString"].ConnectionString);
            
            
            return _dc;
        }


        public List<User> GetUsers()
        {
             jobhuntrDataContext dataContext = CreateDataContext();
            {
                List<User> users = dataContext.Users.ToList();
                return users;

            }
            
        }

        /// <summary>
        /// Computes HASH for password storage
        /// </summary>
        /// <param name="Message">Data to be hashed</param>
        /// <returns></returns>
        private static string ComputeHash(string Message)
        {
            HashAlgorithm ha = new MD5Cng();

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] HashValue, MessageBytes = UE.GetBytes(Message);
            string strHex = "";

            HashValue = ha.ComputeHash(MessageBytes);
            foreach (byte b in HashValue)
            {
                strHex += String.Format("{0:x2}", b);
            }
            return strHex;
        }

        /// <summary>
        /// Generates randon string for use as a password salt
        /// </summary>
        /// <returns>Random string</returns>
        private static string GenerateSalt()
        {
            RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
            byte[] rn = new byte[5];
            Gen.GetBytes(rn);
            string salt = "";

            foreach (byte n in rn)
            {
                salt += string.Format("{0:x2}", n);
            }

            return salt;

        }
    }
}
